﻿using System;

namespace IntegrationTests.QueryToSQLTests
{
    using System.Data;
    using System.Diagnostics;
    using System.DirectoryServices.Protocols;
    using DirectoryServicesProtocolsExtensions.SearchRequest;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using DirectoryServicesProtocolsExtensions.SearchResult;

    [TestClass]
    public class QueryToSqlTableDataTests : DirectoryTest
    {
        [TestInitialize]
        public void TestInit()
        {
            TestInitialize();
        }

        [TestMethod]
        public void ToDataTableTestUserObject()
        {
            var ldapConnection = LdapConnectionFactory.Create();

            LdapSearchRequestPropertiesContainer.SearchBaseDN = "CN=Administrator,CN=Users,DC=fabrikam,DC=com";
            LdapSearchRequestPropertiesContainer.AttributesToLoad = new[]
                {"distinguishedname", "objectGUID", "memberof"};
            LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute = "objectGUID";
            

            var pagedSearchRequest = new PagedSearchRequest(LdapSearchRequestPropertiesContainer);
            var resultingTable = pagedSearchRequest.BuildDataTableToHoldResults(ldapConnection, LdapMetaMapFactory);

            foreach (var searchResultEntryCollection in pagedSearchRequest.Execute(ldapConnection))
            {
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                {
                    searchResultEntry.ToDataTable(
                        ldapConnection,
                        LdapMetaMapFactory,
                        resultingTable,
                        LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute);
                    Assert.AreEqual(resultingTable.Columns.Count, pagedSearchRequest.Attributes.Count);
                    Assert.IsNotNull(resultingTable.Columns[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    foreach (DataRow row in resultingTable.Rows)
                    {
                        Assert.IsNotNull(row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                        var primaryKeyValInTable = row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute];
                        var primaryKeyValInSearchResult =
                            new Guid((byte[])searchResultEntry.Attributes[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute][0]);
                        Assert.AreEqual(primaryKeyValInTable, primaryKeyValInSearchResult);
                    }
                }
            }
        }

        [TestMethod]
        public void ToDataTableTestUserObjectEdirectory()
        {
            var ldapConnection = LdapConnectionFactory.Create();

            LdapSearchRequestPropertiesContainer.SearchBaseDN = "CN=alextc,O=IT";
            LdapSearchRequestPropertiesContainer.AttributesToLoad = new[] { "entryDN", "cn" };
            LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute = "entryDN";


            var pagedSearchRequest = new PagedSearchRequest(LdapSearchRequestPropertiesContainer);
            var resultingTable = pagedSearchRequest.BuildDataTableToHoldResults(ldapConnection, LdapMetaMapFactory);

            foreach (var searchResultEntryCollection in pagedSearchRequest.Execute(ldapConnection))
            {
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                {
                    searchResultEntry.ToDataTable(
                        ldapConnection,
                        LdapMetaMapFactory,
                        resultingTable,
                        LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute);
                    Assert.AreEqual(resultingTable.Columns.Count, pagedSearchRequest.Attributes.Count);
                    Assert.IsNotNull(resultingTable.Columns[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    foreach (DataRow row in resultingTable.Rows)
                    {
                        Assert.IsNotNull(row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                        var primaryKeyValInTable = row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute];
                        var primaryKeyValInSearchResult =
                            (searchResultEntry.Attributes[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute][0]);
                        Assert.AreEqual(primaryKeyValInTable, primaryKeyValInSearchResult);
                    }
                }
            }
        }

        [TestMethod]
        public void ToDataTableTestGroupObject()
        {
            var ldapConnection = LdapConnectionFactory.Create();

            LdapSearchRequestPropertiesContainer.SearchBaseDN = "CN=groupWith1501Member,OU=test1001,DC=fabrikam,DC=com";
            LdapSearchRequestPropertiesContainer.AttributesToLoad = new[] {"distinguishedname", "objectGUID", "member"};
            LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute = "objectGUID";


            var pagedSearchRequest = new PagedSearchRequest(LdapSearchRequestPropertiesContainer);
            var resultingTable = pagedSearchRequest.BuildDataTableToHoldResults(ldapConnection, LdapMetaMapFactory);

            foreach (var searchResultEntryCollection in pagedSearchRequest.Execute(ldapConnection))
            {
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                {
                    searchResultEntry.ToDataTable(
                        ldapConnection,
                        LdapMetaMapFactory,
                        resultingTable,
                        LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute);
                    Assert.AreEqual(resultingTable.Columns.Count, pagedSearchRequest.Attributes.Count);
                    Assert.IsNotNull(resultingTable.Columns[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    foreach (DataRow row in resultingTable.Rows)
                    {
                        Assert.IsNotNull(row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                        var primaryKeyValInTable = row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute];
                        var primaryKeyValInSearchResult =
                            new Guid((byte[])searchResultEntry.Attributes[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute][0]);
                        Assert.AreEqual(primaryKeyValInSearchResult, primaryKeyValInTable);
                    }
                }
            }
        }

        [TestMethod]
        public void ToDataTableTestMixedObject()
        {
            var ldapConnection = LdapConnectionFactory.Create();

            LdapSearchRequestPropertiesContainer.SearchBaseDN = "DC=fabrikam,DC=com";
            LdapSearchRequestPropertiesContainer.SearchFilter = "(|(objectCategory=person)(objectClass=group))";
            LdapSearchRequestPropertiesContainer.AttributesToLoad = new[] {"distinguishedname", "objectGUID", "member"};
            LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute = "objectGUID";

            var timer = new Stopwatch();
            timer.Start();

            var pagedSearchRequest = new PagedSearchRequest(LdapSearchRequestPropertiesContainer);
            var resultingTable = pagedSearchRequest.BuildDataTableToHoldResults(ldapConnection, LdapMetaMapFactory);

            foreach (var searchResultEntryCollection in pagedSearchRequest.Execute(ldapConnection))
            {
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                {
                    searchResultEntry.ToDataTable(
                        ldapConnection,
                        LdapMetaMapFactory,
                        resultingTable,
                        LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute);
                    Assert.AreEqual(resultingTable.Columns.Count, pagedSearchRequest.Attributes.Count);
                    Assert.IsNotNull(resultingTable.Columns[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    foreach (DataRow row in resultingTable.Rows)
                    {
                        Assert.IsNotNull(row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    }
                }
            }

            timer.Stop();
            Debug.WriteLine("ObjectGUID MetaMap creation took " + timer.ElapsedMilliseconds);
        }

        [TestMethod]
        public void ToDataTableTestGroupObjectWithDNAsPrimaryKey()
        {
            var ldapConnection = LdapConnectionFactory.Create();

            LdapSearchRequestPropertiesContainer.SearchBaseDN = "CN=groupWith1501Member,OU=test1001,DC=fabrikam,DC=com";
            LdapSearchRequestPropertiesContainer.AttributesToLoad = new[] {"distinguishedname", "objectGUID", "member"};
            LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute = "distinguishedName";


            var pagedSearchRequest = new PagedSearchRequest(LdapSearchRequestPropertiesContainer);
            var resultingTable = pagedSearchRequest.BuildDataTableToHoldResults(ldapConnection, LdapMetaMapFactory);

            foreach (var searchResultEntryCollection in pagedSearchRequest.Execute(ldapConnection))
            {
                foreach (SearchResultEntry searchResultEntry in searchResultEntryCollection)
                {
                    searchResultEntry.ToDataTable(
                        ldapConnection,
                        LdapMetaMapFactory,
                        resultingTable,
                        LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute);
                    Assert.AreEqual(resultingTable.Columns.Count, pagedSearchRequest.Attributes.Count);
                    Assert.IsNotNull(resultingTable.Columns[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                    foreach (DataRow row in resultingTable.Rows)
                    {
                        Assert.IsNotNull(row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute]);
                        var primaryKeyValInTable = row[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute];
                        var primaryKeyValInSearchResult =
                            searchResultEntry.Attributes[LdapSearchRequestPropertiesContainer.UniqueObjectIdentifierAttribute][0].ToString();
                        Assert.AreEqual(primaryKeyValInSearchResult, primaryKeyValInTable);
                    }
                }
            }
        }
    }
}
